package com.alinesno.cloud.base.notice.service.impl;

import java.util.List;
import java.util.Map;

import javax.lang.exception.RpcServiceRuntimeException;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.alinesno.cloud.base.notice.dto.WechatMessageDto;
import com.alinesno.cloud.base.notice.entity.EmailSendEntity;
import com.alinesno.cloud.base.notice.entity.SmsFailEntity;
import com.alinesno.cloud.base.notice.entity.SmsHistoryEntity;
import com.alinesno.cloud.base.notice.entity.SmsSendEntity;
import com.alinesno.cloud.base.notice.entity.SmsTaskEntity;
import com.alinesno.cloud.base.notice.enums.NoticeSendTypeEnum;
import com.alinesno.cloud.base.notice.service.INoticeSendService;
import com.alinesno.cloud.base.notice.service.ISmsFailService;
import com.alinesno.cloud.base.notice.service.ISmsHistoryService;
import com.alinesno.cloud.base.notice.service.ISmsTaskService;
import com.alinesno.cloud.base.notice.strategy.EmailSendStrategy;
import com.alinesno.cloud.base.notice.strategy.SmsSendStrategy;
import com.alinesno.cloud.base.notice.wechat.IWechatNoticeService;
import com.alinesno.cloud.common.core.context.ApplicationContextProvider;

/**
 * 通知服务 
 * @author WeiXiaoJin
 * @since 2019年10月1日 下午9:44:27
 */
@Service
public class NoticeSendServiceImpl implements INoticeSendService {

	private static final Logger log = LoggerFactory.getLogger(NoticeSendServiceImpl.class);

	@Autowired
	private IWechatNoticeService wechatNoticeService ; 
	
	@Autowired
	private ISmsFailService failService ; 
	
	@Autowired
	private ISmsHistoryService hisService ; 
	
	@Autowired
	private ISmsTaskService taskService ; 

	@Override
	public SmsSendEntity sendRealtimeSms(SmsSendEntity sms, NoticeSendTypeEnum noticeSendTypeEnum) {
		
		Object smsSendServiceObj = ApplicationContextProvider.getBean(noticeSendTypeEnum.value()+"_SendService");
		Assert.notNull(smsSendServiceObj , "发送短信实体不能为空。");
		SmsSendStrategy smsSendService = (SmsSendStrategy)smsSendServiceObj ; 
		
		// 1. 成功则插入历史表
		SmsHistoryEntity e = new SmsHistoryEntity() ; 
		e.setSendStatus(SEND_DOING);
		BeanUtils.copyProperties(sms, e);
		hisService.save(e); 
		
		// 2. 发送短信
		SmsSendEntity response;
		try {
			response = smsSendService.sendSms(sms).getBody();
			log.debug("send {} msg , response = {}" , sms.getPhone() ,  ToStringBuilder.reflectionToString(response));
		} catch (Exception e1) {
			e1.printStackTrace();
			throw RpcServiceRuntimeException.error(e1.getMessage()) ; 
		} 
		return null;
	}

	
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	@Override
	public SmsSendEntity sendSms(SmsSendEntity sms, NoticeSendTypeEnum noticeSendTypeEnum) throws Exception {

		Object smsSendServiceObj = ApplicationContextProvider.getBean(noticeSendTypeEnum.value()+"_SendService");
		Assert.notNull(smsSendServiceObj , "发送短信实体不能为空。");
	
		String smsId = null ; 
		try {
			
			SmsSendStrategy smsSendService = (SmsSendStrategy)smsSendServiceObj ; 
			
			// 1. 成功则插入历史表
			SmsHistoryEntity e = new SmsHistoryEntity() ; 
			e.setSendStatus(SEND_DOING);
			BeanUtils.copyProperties(sms, e);
			hisService.save(e); 
			smsId = e.getId() ; 
			
			// 2. 发送短信
			SmsSendEntity response = smsSendService.sendSms(sms).getBody() ; 
			log.debug("send {} msg , response = {}" , sms.getPhone() ,  ToStringBuilder.reflectionToString(response));

			// 3. 更新发送成功状态
			e.setSendStatus(SEND_SUCCESS);
			hisService.save(e); 
			
			return response ; //smsSendService.sendSms(sms).getBody() ; 
		} catch (Exception e) {
			e.printStackTrace();
			
			// 5. 失败则插入异常表
			SmsTaskEntity t = new SmsTaskEntity() ; 
			BeanUtils.copyProperties(sms, t);
			
			t.setStrategy(noticeSendTypeEnum.value());
			t.setResendCount(0);
			t.setFieldProp(smsId); // 保存未成功的ID
			taskService.save(t); 
			
			// 6. 插入失败表
			SmsFailEntity f = new SmsFailEntity();
			BeanUtils.copyProperties(sms, f);
			f.setFailReason(e.getMessage());
			failService.save(f) ;
			
			throw RpcServiceRuntimeException.error(e.getMessage()) ; 
		} 
		
	}

	@Override
	public SmsSendEntity sendTemplateSms(String templateName, SmsSendEntity sms, NoticeSendTypeEnum noticeSendTypeEnum) {
		
		return null;
	}

	@Override
	public SmsSendEntity sendBatchSms(List<String> sms, String subject, String htmlBody, NoticeSendTypeEnum noticeSendTypeEnum) {
		return null;
	}

	@Override
	public void sendWechatMessage(Map<String, Object> messageKey, WechatMessageDto message) {
		wechatNoticeService.sendMessage(messageKey , message) ;
	}

	@Override
	public EmailSendEntity sendTextEmail(EmailSendEntity email, NoticeSendTypeEnum noticeSendTypeEnum) {
		
		Assert.notNull(noticeSendTypeEnum , "邮件通知发送策略不能为空.");
		log.debug("发送邮件策略:{}" , noticeSendTypeEnum.value());
		
		EmailSendStrategy service ;
		
		try {
			service = (EmailSendStrategy) ApplicationContextProvider.getBean(noticeSendTypeEnum.value()+"_SendService");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RpcServiceRuntimeException("消息推送接口["+noticeSendTypeEnum.value()+"_SendService]未实现:"+e.getMessage()) ; 
		} 
		
		return service.sendTextEmail(email).getBody() ; 
		
	}


	@Override
	public EmailSendEntity sendHtmlEmail(EmailSendEntity email, NoticeSendTypeEnum noticeSendTypeEnum) throws Exception {
		Assert.notNull(noticeSendTypeEnum , "邮件通知发送策略不能为空.");
		log.debug("发送邮件策略:{}" , noticeSendTypeEnum.value());
		
		EmailSendStrategy service ;
		
		try {
			service = (EmailSendStrategy) ApplicationContextProvider.getBean(noticeSendTypeEnum.value()+"_SendService");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RpcServiceRuntimeException("消息推送接口["+noticeSendTypeEnum.value()+"_SendService]未实现:"+e.getMessage()) ; 
		} 
		
		return service.sendHtmlEmail(email).getBody() ; 
	}

	@Override
	public EmailSendEntity sendTemplateEmail(Map<String, Object> maps, String templateName, EmailSendEntity email,
			NoticeSendTypeEnum noticeSendTypeEnum) {
		
		return null;
	}

	@Override
	public EmailSendEntity sendBatchTextEmail(List<EmailSendEntity> emails, String subject, String htmlBody,
			NoticeSendTypeEnum noticeSendTypeEnum) {
		
		return null;
	}

	@Override
	public EmailSendEntity sendBatchHtmlEmail(List<EmailSendEntity> emails, String subject, String htmlBody,
			NoticeSendTypeEnum noticeSendTypeEnum) {
		
		return null;
	}
	
	
}
